﻿using System;
using System.IO;
using System.Configuration;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Web;
using System.Net;
using Hxsoft.AppV1;

namespace Hxsoft.AppV1.Module
{
	/// <summary>
	/// CachePages 类。
	/// </summary>
	public static partial class CachePages
	{
		public const string INFO_TYPE = "CachePage";
		public const string ClassDicClassCode = "CachePageClass";
		public const string AutoBuildLogFileName = "BuildCachePageLog.txt";



		#region GetItem
		/// <summary>
		/// 根据标识获取指定的缓存页。
		/// </summary>
		/// <param name="o">缓存页集合。</param>
		/// <param name="id">获取的缓存页标识 Id。</param>
		/// <returns>获取的信息项。</returns>
		public static CachePage GetItem(this System.Data.Linq.Table<CachePage> o, int id)
		{
			return o.SingleOrDefault(p => p.Id == id);
		}

		/// <summary>
		/// 根据标识获取指定的缓存页。
		/// </summary>
		/// <param name="id">获取的缓存页标识 Id。</param>
		/// <returns>获取的信息项。</returns>
		public static CachePage GetItem(int id)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.CachePages.GetItem(id);
		}
		#endregion



		#region GetItems
		/// <summary>
		/// 获取指定的缓存页集合。
		/// </summary>
		/// <param name="o">缓存页集合。</param>
		/// <param name="siteId">缓存页所属的站点。</param>
		/// <param name="classId">缓存页的类别。</param>
		/// <param name="isAutoBuild">是否为自动构建缓存页。</param>
		/// <returns>指定的缓存页集合。</returns>
		public static List<CachePage> GetItems(this System.Data.Linq.Table<CachePage> o, int? siteId, int? classId, bool? isAutoBuild)
		{
			var q = from p in o
					select p;

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (classId.HasValue)
				q = q.Where(p => p.ClassId == classId.Value);

			if (isAutoBuild.HasValue)
				q = q.Where(p => p.IsAutoBuild == isAutoBuild.Value);

			return q.OrderBy(p => p.SiteId).OrderBy(p => p.ClassId).ToList();
		}

		/// <summary>
		/// 获取指定的缓存页集合。
		/// </summary>
		/// <param name="siteId">缓存页所属的站点。</param>
		/// <param name="classId">缓存页的类别。</param>
		/// <param name="isAutoBuild">是否为自动构建缓存页。</param>
		/// <returns>指定的缓存页集合。</returns>
		public static List<CachePage> GetItems(int? siteId, int? classId, bool? isAutoBuild)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.CachePages.GetItems(siteId, classId, isAutoBuild);
		}
		#endregion



		#region Exists
		/// <summary>
		/// 验证指定的缓存页是否已经存在。
		/// </summary>
		/// <param name="o">缓存页集合。</param>
		/// <param name="id">验证的缓存页标识 Id。</param>
		/// <returns>布尔值表示指定的缓存页是否已经存在。</returns>
		public static bool Exists(this System.Data.Linq.Table<CachePage> o, int id)
		{
			return o.Any(p => p.Id == id);
		}

		/// <summary>
		/// 验证指定的缓存页是否已经存在。
		/// </summary>
		/// <param name="id">验证的缓存页标识 Id。</param>
		/// <returns>布尔值表示指定的缓存页是否已经存在。</returns>
		public static bool Exists(int id)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;
			return dc.CachePages.Exists(id);
		}
		#endregion
	}



	/// <summary>
	/// CachePages 类操作部分。
	/// </summary>
	public static partial class CachePages
	{
		#region Insert
		/// <summary>
		/// 添加缓存页。
		/// </summary>
		/// <param name="insertedCachePage">添加的缓存页。</param>
		/// <returns>添加的缓存页。</returns>
		public static CachePage Insert(CachePage insertedCachePage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			CachePage cachePage = insertedCachePage.ToNewEntity<CachePage>();
			cachePage.CreationDate = DateTime.Now;

			GetInsertRight(dc, cachePage, true);	// 权限验证

			dc.CachePages.InsertOnSubmit(cachePage);
			dc.SubmitChanges();

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Insert, INFO_TYPE, cachePage.Id.ToString(), PermissionCode.Insert.ToString(), cachePage.Name);

			// 返回只读数据
			return insertedCachePage.FillByEntity(cachePage);
		}
		#endregion



		#region Update
		private static readonly HashSet<string> _updatedExcludeColumns = typeof(CachePage).GetEntityColumnNames(new string[] {
				"Id",
				"SiteId",
				"LastBuildDate",
				"CreationDate"
			}, true);

		/// <summary>
		/// 修改缓存页。
		/// </summary>
		/// <param name="updatedCachePage">修改的缓存页。</param>
		/// <returns>修改的缓存页。</returns>
		public static CachePage Update(CachePage updatedCachePage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			CachePage cachePage = dc.CachePages.GetItem(updatedCachePage.Id);
			if (cachePage == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetUpdateRight(dc, cachePage, true);	// 权限验证

			cachePage.FillByEntity(updatedCachePage, EntityColumnsSetType.Exclude, _updatedExcludeColumns);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Update, INFO_TYPE, cachePage.Id.ToString(), PermissionCode.Update.ToString(), cachePage.Name);

			// 返回只读数据
			return updatedCachePage.FillByEntity(cachePage);
		}
		#endregion



		#region Delete
		/// <summary>
		/// 删除缓存页。
		/// </summary>
		/// <param name="id">删除的缓存页标识 Id。</param>
		public static void Delete(int id)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			CachePage cachePage = dc.CachePages.GetItem(id);
			if (cachePage == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			GetDeleteRight(dc, cachePage, true);	// 权限验证

			Delete(dc, cachePage);

			dc.SubmitChanges();

			// 记录日志
			Logs.Insert(dc, ResourceId, (int)PermissionCode.Delete, INFO_TYPE, cachePage.Id.ToString(), PermissionCode.Delete.ToString(), cachePage.Name);
		}

		#region internal Delete
		internal static void Delete(GenericModuleDataContext dc, CachePage cachePage)
		{
			dc.CachePages.DeleteOnSubmit(cachePage);
		}
		#endregion
		#endregion



		#region BuildCachePage
		/// <summary>
		/// 获取缓存页的HTML。
		/// </summary>
		/// <param name="cachePage">缓存页配置。</param>
		/// <returns>缓存页的HTML。</returns>
		public static string GetCachePageHtml(CachePage cachePage)
		{
			if (cachePage == null) return null;

			Site site = Sites.GetItem(cachePage.SiteId);
			if (site == null) return null;

			string domain = site.MainDomain;
			if (string.IsNullOrEmpty(domain))
			{
				var context = HttpContext.Current;
				if (context != null) domain = context.Request.Url.Host.ToLower();
			}
			if (string.IsNullOrEmpty(domain)) return null;

			string url = "http://" + domain;
			url = url.TrimEnd(' ').TrimEnd('/');
			url += cachePage.PageUrl;

			return Hxsoft.Web.Util.Net.GetHttpData(url);
		}



		/// <summary>
		/// 构建缓存页。
		/// </summary>
		/// <param name="cachePage">缓存页配置。</param>
		private static void BuildCachePage(CachePage cachePage)
		{
			if (cachePage == null || string.IsNullOrEmpty(cachePage.BuildPath)) return;

			string path = SiteBaseInfo.GetSiteApplicationPath(cachePage.SiteId);		// 通过 WebService 获取应用程序部署路径。
			if (string.IsNullOrEmpty(path))		// 通过配置文件获取应用程序部署路径。
				path = ConfigurationManager.AppSettings["CachePageRootPath_" + cachePage.SiteId];
			if (string.IsNullOrEmpty(path))		// 获取当前应用程序路径。
				path = HttpRuntime.AppDomainAppPath;
			if (string.IsNullOrEmpty(path)) return;

			path = path.TrimEnd(' ').TrimEnd('\\');
			path = path + cachePage.BuildPath;

			string html = GetCachePageHtml(cachePage);
			if (!string.IsNullOrEmpty(html))
			{
				lock (html)
				{
					try
					{
						System.IO.Directory.CreateDirectory(Path.GetDirectoryName(path));
						var stream = File.CreateText(path);
						stream.Write(html);
						stream.Close();
					}
					catch (Exception err)
					{
						return;
					}
				}

				cachePage.LastBuildDate = DateTime.Now;
			}
		}

		/// <summary>
		/// 构建缓存页。
		/// </summary>
		/// <param name="id">缓存页的ID。</param>
		public static void BuildCachePage(int id)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			CachePage cachePage = dc.CachePages.GetItem(id);
			if (cachePage == null)
				throw new ObjectNotExistsException(Res.Operation_ObjectNotExists);

			BuildCachePage(cachePage);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}
		}

		/// <summary>
		/// 构建缓存页。
		/// </summary>
		/// <param name="siteId">构建缓存页的所属站点。</param>
		/// <param name="isAutoBuild">是否只生成自动生成页。</param>
		public static void BuildCachePage(int? siteId, bool? isAutoBuild)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();

			var q = from p in dc.CachePages select p;
			if (siteId.HasValue) q = q.Where(p => p.SiteId == siteId.Value);
			if (isAutoBuild.HasValue) q = q.Where(p => p.IsAutoBuild == isAutoBuild.Value);
			var cachePages = q.OrderBy(p => p.SiteId).ToArray();

			foreach(var cachePage in cachePages)
				BuildCachePage(cachePage);

			try
			{
				dc.SubmitChanges(ConflictMode.ContinueOnConflict);
			}
			catch (ChangeConflictException e)
			{
				foreach (ObjectChangeConflict occ in dc.ChangeConflicts)
				{
					occ.Resolve(RefreshMode.KeepCurrentValues);
				}
			}
		}
		#endregion
	}



	/// <summary>
	/// CachePages 类对应操作权限部分。（受限站点资源。）
	/// </summary>
	public static partial class CachePages
	{
		#region GetInsertRight
		/// <summary>
		/// 获取当前用户是否有添加缓存页的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="cachePage">添加的缓存页对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加缓存页的权限。</returns>
		public static bool GetInsertRight(GenericModuleDataContext dc, CachePage cachePage, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Insert;
			bool b = dc.AccessController.GetUserIsHasPermission<CachePage>(userName, cachePage, ResourceId, permissionCode, cachePage.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, cachePage, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有添加缓存页的权限。
		/// </summary>
		/// <param name="cachePage">添加的缓存页对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有添加缓存页的权限。</returns>
		public static bool GetInsertRight(CachePage cachePage, bool triggerException)
		{
			return GetInsertRight(new GenericModuleDataContext(), cachePage, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有添加缓存页的权限。
		/// </summary>
		/// <param name="cachePage">添加的缓存页对象。</param>
		/// <returns>布尔值表示当前用户是否有添加缓存页的权限。</returns>
		public static bool GetInsertRight(CachePage cachePage)
		{
			return GetInsertRight(cachePage, false);
		}
		#endregion



		#region GetUpdateRight
		/// <summary>
		/// 获取当前用户是否有更新缓存页的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="cachePage">更新的缓存页对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有更新缓存页的权限。</returns>
		public static bool GetUpdateRight(GenericModuleDataContext dc, CachePage cachePage, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Update;
			bool b = dc.AccessController.GetUserIsHasPermission<CachePage>(userName, cachePage, ResourceId, permissionCode, cachePage.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, cachePage, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有更新缓存页的权限。
		/// </summary>
		/// <param name="cachePage">更新的缓存页对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有更新缓存页的权限。</returns>
		public static bool GetUpdateRight(CachePage cachePage, bool triggerException)
		{
			return GetUpdateRight(new GenericModuleDataContext(), cachePage, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有更新缓存页的权限。
		/// </summary>
		/// <param name="cachePage">更新的缓存页对象。</param>
		/// <returns>布尔值表示当前用户是否有更新缓存页的权限。</returns>
		public static bool GetUpdateRight(CachePage cachePage)
		{
			return GetUpdateRight(cachePage, false);
		}
		#endregion



		#region GetDeleteRight
		/// <summary>
		/// 获取当前用户是否有删除缓存页的权限。
		/// </summary>
		/// <param name="dc">数据容器。</param>
		/// <param name="cachePage">删除的缓存页对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除缓存页的权限。</returns>
		public static bool GetDeleteRight(GenericModuleDataContext dc, CachePage cachePage, bool triggerException)
		{
			string userName = Users.CurrentUserName;
			int permissionCode = (int)PermissionCode.Delete;
			bool b = dc.AccessController.GetUserIsHasPermission<CachePage>(userName, cachePage, ResourceId, permissionCode, cachePage.SiteId);

			if (triggerException && !b)
				throw new PermissionException(userName, cachePage, ResourceId, permissionCode, Res.PermissionExceptionMessage);
			return b;
		}

		/// <summary>
		/// 获取当前用户是否有删除缓存页的权限。
		/// </summary>
		/// <param name="cachePage">删除的缓存页对象。</param>
		/// <param name="triggerException">当未通过权限验证的时候是否引发异常。</param>
		/// <returns>布尔值表示当前用户是否有删除缓存页的权限。</returns>
		public static bool GetDeleteRight(CachePage cachePage, bool triggerException)
		{
			return GetDeleteRight(new GenericModuleDataContext(), cachePage, triggerException);
		}

		/// <summary>
		/// 获取当前用户是否有删除缓存页的权限。
		/// </summary>
		/// <param name="cachePage">删除的缓存页对象。</param>
		/// <returns>布尔值表示当前用户是否有删除缓存页的权限。</returns>
		public static bool GetDeleteRight(CachePage cachePage)
		{
			return GetDeleteRight(cachePage, false);
		}
		#endregion
	}



	/// <summary>
	/// CachePages 类后台管理部分。
	/// </summary>
	public static partial class CachePages
	{
		public static bool GetManageListRight()
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			return dc.AccessController.GetUserIsHasPermission<object>(Users.CurrentUserName, null, CachePages.ResourceId, (int)CachePages.PermissionCode.Delete, Sites.CurrentSiteId);
		}

		public static bool GetManageListRight(int? siteId)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
            return dc.AccessController.GetUserIsHasPermission<object>(Users.CurrentUserName, null, CachePages.ResourceId, (int)CachePages.PermissionCode.Insert, siteId);
		}

		public static PaginationInfo<List<CachePage>> GetPaginationManageList(int? siteId, string keyword, int pageSize, int currentPage)
		{
			GenericModuleDataContext dc = new GenericModuleDataContext();
			dc.ObjectTrackingEnabled = false;

			var q = from p in dc.CachePages
					select p;

			if (siteId.HasValue)
				q = q.Where(p => p.SiteId == siteId.Value);

			if (!string.IsNullOrEmpty(keyword))
				q = q.Where(p => p.Name.Contains(keyword));

			PaginationInfo<List<CachePage>> pageInfo = new PaginationInfo<List<CachePage>>();
			pageInfo.PageSize = pageSize;
			pageInfo.CurrentPage = currentPage;
			pageInfo.RecordCount = q.Count();
			pageInfo.Records = q.Skip((currentPage - 1) * pageSize).Take(pageSize).ToList();
			return pageInfo;
		}
	}
}